﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.ComponentModel;
using PhoneStore.Entity;
using PhoneStore.DataAccess;
using System.Windows.Data;
using System.Data.Objects.DataClasses;

namespace PhoneStore.Presentation.CompositeControl
{
    public abstract class BaseList<T> : UserControl, INotifyPropertyChanged where T : EntityObject
    {
        ICollectionView gridview;
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            ItemsGrid = new DataGrid()
            {
                CanUserAddRows = false,
                CanUserDeleteRows = false,
                IsReadOnly = true,
                AutoGenerateColumns = false,
                SelectionMode = DataGridSelectionMode.Single,
                Height = 300
            };

            SetUpGrid();

            StackPanel stack = new StackPanel { Orientation = Orientation.Horizontal };
            leftSt = new StackPanel();
            stack.Children.Add(leftSt);
            StackPanel rightSt = new StackPanel();
            stack.Children.Add(rightSt);
            StackPanel spFilter = new StackPanel { Orientation = System.Windows.Controls.Orientation.Horizontal };
            Label lbFilter = new Label { Content = "Search" };
            spFilter.Children.Add(lbFilter);
            txtFilter = new TextBox() { Width = 200};
            txtFilter.TextChanged += new TextChangedEventHandler(txtFilter_TextChanged);
            spFilter.Children.Add(txtFilter);
            leftSt.Children.Add(spFilter);
            leftSt.Children.Add(ItemsGrid);
            leftSt.Children.Add(ButtonsPanel);
            rightSt.Children.Add(ItemPanel);
            StackPanel RightStCmd = new StackPanel() { Orientation = Orientation.Horizontal };
            btnSave = new Button() { Content = "Save" };
            btnSave.Click += new System.Windows.RoutedEventHandler(btnSave_Click);
            btnCancel = new Button() { Content = "Cancel" };
            btnCancel.Click += new System.Windows.RoutedEventHandler(btnCancel_Click);
            RightStCmd.Children.Add(btnSave);
            RightStCmd.Children.Add(btnCancel);
            rightSt.Children.Add(RightStCmd);
            btnCreate = new Button { Content = "Tạo" };
            btnCreate.Click += new System.Windows.RoutedEventHandler(btnCreate_Click);
            btnDelete = new Button { Content = "Xóa" };
            btnDelete.Click += new System.Windows.RoutedEventHandler(btnDelete_Click);
            btnUpdate = new Button { Content = "Sửa" };
            btnUpdate.Click += new System.Windows.RoutedEventHandler(btnUpdate_Click);
            StackPanel stkManBut = new StackPanel { Orientation = Orientation.Horizontal };
            stkManBut.Children.Add(btnUpdate);
            stkManBut.Children.Add(btnCreate);
            stkManBut.Children.Add(btnDelete);
            leftSt.Children.Add(stkManBut);
            btnUpdate.IsEnabled = false;
            btnDelete.IsEnabled = false;
            this.Content = stack;
        }

        void txtFilter_TextChanged(object sender, TextChangedEventArgs e)
        {
            gridview.Refresh();
        }

        void btnUpdate_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            SetEditItemMode(false);
        }

        void btnDelete_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            try
            {
                DAO.Delete(SelectedItem);
            }
            catch (Exception ex)
            {
                ExceptionDitpatcher(ex);
            }
            RefreshItemsGrid();
        }

        void btnCreate_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            SetEditItemMode(true);
        }

        TextBox txtFilter;
        Button btnSave;
        Button btnCancel;
        StackPanel leftSt;
        Button btnCreate;
        Button btnUpdate;
        Button btnDelete;

        public void SetUp(Action<bool> enableEditItemFunc, bool isManageMode, Func<string> checkErrFunc)
        {
            CheckErrorFunc = checkErrFunc;
            IsManageMode = isManageMode;
            EnableEditItemFunc = enableEditItemFunc;
            SetReadMode();
        }

        protected bool IsManageMode
        {
            set
            {
                if (value)
                {
                    btnDelete.Visibility = btnUpdate.Visibility =
                        btnCreate.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    btnDelete.Visibility = btnUpdate.Visibility =
                        btnCreate.Visibility = System.Windows.Visibility.Hidden;
                }
            }
        }

        public void SetEditItemMode(bool isCreate)
        {
            btnCancel.Visibility = System.Windows.Visibility.Visible;
            btnSave.Visibility = System.Windows.Visibility.Visible;
            leftSt.Visibility = System.Windows.Visibility.Hidden;
            if (isCreate)
            {
                SaveFunc = () => DAO.Add(SelectedItem);
                SelectedItem = GetBlankEntity();
            }
            else
            {
                SaveFunc = () => DAO.Update(SelectedItem);
            }
            EnableEditItemFunc(true);
        }

        protected void SetReadMode()
        {
            leftSt.Visibility = System.Windows.Visibility.Visible;
            btnSave.Visibility = System.Windows.Visibility.Hidden;
            btnCancel.Visibility = System.Windows.Visibility.Hidden;
            EnableEditItemFunc(false);
            RefreshItemsGrid();
        }

        public Action SaveFunc;
        public Action<bool> EnableEditItemFunc;

        void btnCancel_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            SetReadMode();
        }

        protected virtual void ExceptionDitpatcher(Exception e)
        {
            System.Windows.MessageBox.Show("Đã có lỗi xảy ra. Hãy thử lại");
        }

        void btnSave_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            string errs = CheckErrorFunc();
            if (String.IsNullOrEmpty(errs))
            {
                try
                {
                    SaveFunc();
                }
                catch(Exception ex)
                {
                    ExceptionDitpatcher(ex);
                }
                SetReadMode();
            }
            else
            {
                System.Windows.MessageBox.Show(errs);
            }
        }

        Func<string> CheckErrorFunc;

        protected virtual void SetUpGrid()
        {
            ItemsGrid.SelectionChanged += new SelectionChangedEventHandler(ItemsGrid_SelectionChanged);
        }

        protected void ItemsGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var item = ItemsGrid.SelectedItem as T;
            if (item != null)
                SelectedItem = GetSingleEntity(item);
            else
                SelectedItem = item;
        }

        protected DataGrid ItemsGrid;
        public ContentControl ItemPanel { get; set; }
        public ContentControl ButtonsPanel { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string status)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(status));
            }
        }

        public IList<T> ListSource
        {
            get
            {
                return ItemsGrid.ItemsSource as IList<T>;
            }
            set
            {
                ItemsGrid.ItemsSource = value;
                gridview = CollectionViewSource.GetDefaultView(value);
                gridview.Filter = TextFilter;
            }
        }

        public bool TextFilter(object o)
        {
            if (txtFilter.Text == "")
                return true;
            T p = (o as T);
            if (p == null)
                return false;
            return FilterEntity(p,txtFilter.Text);
        }

        protected abstract bool FilterEntity(T obj,string val);

        protected T _selectedItem = null;

        public T SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                if (value == null)
                {
                    btnUpdate.IsEnabled = btnDelete.IsEnabled = false;
                }
                else
                {
                    btnUpdate.IsEnabled = btnDelete.IsEnabled = true;
                }
                ItemPanel.DataContext = value;
                _selectedItem = value;
            }
        }

        protected abstract void RefreshItemsGrid();

        protected abstract T GetBlankEntity();

        protected abstract T GetSingleEntity(T obj);

        BaseDAO _dao = null;
        protected BaseDAO DAO
        {
            get
            {
                if (_dao == null)
                    _dao = new BaseDAO();
                return _dao;
            }
        }
    }

    public class PhoneList : BaseList<Phone>
    {
        protected override void SetUpGrid()
        {
            base.SetUpGrid();
            _IsInSearchMode = false;
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Product.Manufacturer"), Header = "Nhà sản xuất" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Product.Model"), Header = "Tên Sản phẩm" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Product.Price"), Header = "Giá" });
        }

        protected override bool FilterEntity(Phone obj,string val)
        {
            if (obj.Product.Model == null)
                return false;
            return obj.Product.Model.Contains(val);
        }

        protected override Phone GetSingleEntity(Phone obj)
        {
            return DAO.Single<Phone>(x => x.PhoneId == obj.PhoneId, "Product");
        }

        protected override Phone GetBlankEntity()
        {
            return new Phone()
            {
                Product = new Product()
            };
        }

        protected override void RefreshItemsGrid()
        {
            if (!IsInSearchMode)
            {
                ListSource = DAO.GetAll<Phone>("Product");
            }
            else
            {
                ListSource = SearchSource;
            }
        }

        bool _IsInSearchMode;
        public bool IsInSearchMode {
            get
            {
                return _IsInSearchMode;
            }
            set
            {
                _IsInSearchMode = value;
                RefreshItemsGrid();
            }
        }
        IList<Phone> SearchSource { get; set; }

        public void SetSearchResult(IQueryable<Phone> src)
        {
            SearchSource = src.ToList();
            IsInSearchMode = true;
        }
    }

    public class ProductList : BaseList<Product>
    {
        protected override void SetUpGrid()
        {
            base.SetUpGrid();
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Manufacturer"), Header = "Nhà sản xuất" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Model"), Header = "Tên Sản phẩm" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Price"), Header = "Giá" });
        }

        protected override Product GetSingleEntity(Product obj)
        {
            return DAO.Single<Product>(x => x.ProductID == obj.ProductID);
        }

        protected override bool FilterEntity(Product obj, string val)
        {
            if (obj.Model == null)
                return false;
            return obj.Model.Contains(val);
        }

        protected override Product GetBlankEntity()
        {
            return new Product();
        }

        protected override void RefreshItemsGrid()
        {
            ListSource = DAO.GetAll<Product>(x => x.Phone == null);
        }
    }

    public class StaffList : BaseList<Staff>
    {
        protected override void SetUpGrid()
        {
            base.SetUpGrid();
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Username"), Header = "Tên tài khoản" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Fullname"), Header = "Tên Nhân viên" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Phone"), Header = "Số điện thoại" });
        }

        protected override Staff GetSingleEntity(Staff obj)
        {
            return DAO.Single<Staff>(x => x.ID == obj.ID);
        }

        protected override bool FilterEntity(Staff obj, string val)
        {
            if (obj.Fullname == null)
                return false;
            return obj.Fullname.Contains(val);
        }

        protected override Staff GetBlankEntity()
        {
            return new Staff();
        }

        protected override void RefreshItemsGrid()
        {
            ListSource = DAO.GetAll<Staff>();
        }
    }

    public class CustomerList : BaseList<Customer>
    {
        protected override void SetUpGrid()
        {
            base.SetUpGrid();
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Fullname"), Header = "Tên Khách Hàng" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Kind.Description"), Header = "Loại Khách Hàng" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Phone"), Header = "Số điện thoại" });
        }

        protected override Customer GetSingleEntity(Customer obj)
        {
            return DAO.Single<Customer>(x => x.PersonID == obj.PersonID,"Kind");
        }

        protected override bool FilterEntity(Customer obj, string val)
        {
            if (obj.Fullname == null)
                return false;
            return obj.Fullname.Contains(val);
        }

        protected override Customer GetBlankEntity()
        {
            return new Customer()
                {
                };
        }

        protected override void RefreshItemsGrid()
        {
            ListSource = DAO.GetAll<Customer>("Kind");
        }
    }

    public class BillList : BaseList<Bill>
    {
        protected override void SetUpGrid()
        {
            base.SetUpGrid();
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("BillID"), Header = "Mã Hóa Đơn" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Staff.Fullname"), Header = "Nhân Viên Bán Hàng" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("SellDate"), Header = "Ngày Bán" });
        }

        protected override Bill GetSingleEntity(Bill obj)
        {
            return DAO.Single<Bill>(x => x.BillID == obj.BillID, "Customer","Staff");
        }

        protected override bool FilterEntity(Bill obj, string val)
        {
            return obj.BillID.ToString().Contains(val);
        }

        protected override Bill GetBlankEntity()
        {
            return new Bill()
            {
            };
        }

        protected override void RefreshItemsGrid()
        {
            ListSource = DAO.GetAll<Bill>("Customer", "Staff");
        }
    }

    public class BillDetailList : BaseList<BillDetail>
    {
        public int BillID { get; set; }

        protected override void SetUpGrid()
        {
            base.SetUpGrid();
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("BillID"), Header = "Mã Hóa Đơn" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Product.Model"), Header = "Tên mặt hàng" });
            ItemsGrid.Columns.Add(new DataGridTextColumn { Binding = new Binding("Amount"), Header = "Số lượng" });
        }

        protected override BillDetail GetSingleEntity(BillDetail obj)
        {
            return DAO.Single<BillDetail>(x => (x.BillID == obj.BillID && x.ProductID == obj.ProductID ), "Product");
        }

        protected override bool FilterEntity(BillDetail obj, string val)
        {
            return obj.Product.Model.Contains(val);
        }

        protected override BillDetail GetBlankEntity()
        {
            return new BillDetail()
            {
                BillID = BillID
            };
        }

        protected override void RefreshItemsGrid()
        {
            ListSource = DAO.GetAll<BillDetail>(x=> x.BillID == BillID,"Product");
        }

        protected override void ExceptionDitpatcher(Exception e)
        {
            System.Windows.Forms.MessageBox.Show("Sản Phẩm đã tồn tại trong danh sách");
        }
    }
}
